
/* Generated by Interface Builder */

#import "WaterfallView.h"
#import <appkit/appkit.h>
#import <appkit/PrintInfo.h>

double wf_back_ground = 0.0/3.0, wf_draw_gray = 3.0/3.0, wf_marker_gray = 1.0/3.0;
double wf_deltax,wf_deltay,current_plot,wf_length,wf_ynorm,total_plots;
int lastPosition,memoryElements;
float *memoryData;
BOOL wf_not_first_time;

@implementation WaterfallView

- setup: (int) numPlots length: (int) numPoints;
{
    wf_deltax = frame.size.width * 0.2 / (numPlots + 2);
    wf_deltay = frame.size.height  / (numPlots + 2);
    wf_length = numPoints;
    wf_ynorm = [plotHeight floatValue] / (numPlots + 2);
    total_plots = numPlots;
    current_plot = numPlots - 1;
    if (numPlots*numPoints!=memoryElements)	{
        free(memoryData);
	memoryElements = numPlots*numPoints;
	memoryData = (float *) malloc (memoryElements*4);
    }
    [self clear];
    return self;
}

- drawNext: (float *) f;
{
    int i,incr,memoryOffset;
    double xstep,xoffs,yoffs,ymax,max=0.0;
    xstep = frame.size.width * 0.8 / wf_length;
    ymax = wf_ynorm * frame.size.height;
    xoffs = current_plot * wf_deltax;
    yoffs = current_plot * wf_deltay + 2.0;
    incr = 0.8 * wf_length / frame.size.width;
    [self lockFocus];
    [self setOpaque: TRUE];
    PSsetlinewidth(0.1);
    PSsetgray(wf_back_ground);
    PSmoveto(xoffs,0.0);
    PSlineto(xoffs,f[0] * ymax + yoffs);
    memoryOffset = current_plot*wf_length;
    memoryData[memoryOffset] = f[0];
    for (i=1;i<wf_length;i++) {
        memoryData[memoryOffset+i] = f[i];
	if (f[i]>max) max = f[i];
	if (incr==0)	{
	    PSlineto((double) i * xstep + xoffs,max * ymax + yoffs);
	    max = 0.0;	
	}
	else if ((i%incr)==0)	{
	    PSlineto((double) i * xstep+ xoffs,max * ymax + yoffs);
	    max = 0.0;
	}
    }
    PSlineto((double) i * xstep+ xoffs,0.0);
    PSlineto(xoffs,0.0);
    PSfill();
    PSstroke();
    PSflushgraphics();
    PSsetgray(wf_draw_gray);
    PSmoveto(xoffs,f[0] * ymax + yoffs);
    for (i=1;i<wf_length;i++) {
	if (f[i]>max) max = f[i];
	if (incr==0)	{
	    PSlineto((double) i * xstep + xoffs,max * ymax + yoffs);
	    max = 0.0;	
	}
	else if ((i%incr)==0)	{
	    PSlineto((double) i * xstep+ xoffs,max * ymax + yoffs);
	    max = 0.0;
	}
    }
    PSlineto((double) i * xstep+ xoffs,yoffs);
    PSlineto((double) i * xstep + wf_deltax+ xoffs,yoffs);
    PSstroke();
    PSflushgraphics();
    [self unlockFocus];
    current_plot -= 1;
    return self;
}

- placeTickAt: (int) position;
{
    int i;
    lastPosition = position;
    [self lockFocus];
    [self setOpaque: TRUE];
    PSsetlinewidth(0.1);
    PSsetgray(wf_back_ground);
    for (i=0;i<total_plots;i++)	{
        PSmoveto(frame.size.width,wf_deltay * i + 2.0);
        PSlineto(frame.size.width - (total_plots - i) * wf_deltax ,wf_deltay * i + 2.0);
    }
    PSstroke();
    PSflushgraphics();
    PSsetgray(wf_draw_gray);
    PSmoveto(frame.size.width,wf_deltay * position + 2.0);
    PSlineto(frame.size.width - (total_plots - position) * wf_deltax ,wf_deltay * position + 2.0);
    PSstroke();
    PSflushgraphics();
    [self unlockFocus];
    return self;
}

- clear
{
    [self lockFocus];
    [self setOpaque: TRUE];
    PSsetgray(wf_back_ground);
    PSrectfill(0.,0.,bounds.size.width,bounds.size.height);
    PSstroke();
    PSflushgraphics();
    [self unlockFocus];
    return self;
}

- printMyPSCode:sender
{

    int i;
    [[[[[NXApp printInfo] setOrientation:NX_PORTRAIT andAdjust:YES]
	    setHorizCentered:YES]
		    setVertCentered:YES]
			    setMarginLeft:0.0
			    right:0.0
			    top:0.0
			    bottom:0.0];
    
    if (wf_back_ground == 0.0/3.0)	{
	NXRunAlertPanel("Too much black ink for the printer.",
	"I'm going to reverse my colors,\
	 From now on this view will show reverse.",NULL,NULL,"OK"); 
          wf_back_ground = 3.0/3.0;
	  wf_draw_gray = 0.0/3.0;
	  wf_marker_gray = 2.0/3.0 ;
        [self setup:total_plots length: wf_length];
	for (i=total_plots-1;i>=0 ;i--)	
	    [self drawNext:&memoryData[i * (int) wf_length]];
	[self placeTickAt: lastPosition];
    }
    [[self window] printPSCode: sender];	
    return self;      
}

- drawSelf: (NXRect *) r : (int) n 
{
    int i;
    if (wf_not_first_time)   {
        [self setup:total_plots length: wf_length];
	for (i=total_plots-1;i>=0 ;i--)	
	    [self drawNext:&memoryData[i * (int) wf_length]];
	[self placeTickAt: lastPosition];
    }
    else	{
       [self clear];
	wf_not_first_time = TRUE;
    }
    return self;
}
    
@end
